package gov.dhs.cis.soa.readers.rsa;

import gov.dhs.cis.soa.SOAData;
import gov.dhs.cis.soa.Utils;
import gov.dhs.cis.soa.Constants.EntityType;
import gov.dhs.cis.soa.data.AbstractSOAData;
import gov.dhs.cis.soa.data.Application;
import gov.dhs.cis.soa.data.ComponentModel;
import gov.dhs.cis.soa.data.DataClass;
import gov.dhs.cis.soa.data.EntitiesReferences;
import gov.dhs.cis.soa.data.IntegrationComp;
import gov.dhs.cis.soa.data.Interface;
import gov.dhs.cis.soa.data.Processes;
import gov.dhs.cis.soa.data.RelatedProperties;
import gov.dhs.cis.soa.data.Rule;
import gov.dhs.cis.soa.data.RuleSet;
import gov.dhs.cis.soa.data.Service;
import gov.dhs.cis.soa.data.UseCase;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class RateChartExport {
	final String WAVE_STR = "Release";
	final String RELEASE_STR = "Release";
	final boolean isRateChartReport = true;

	final String UML_XMI_NS = "http://schema.omg.org/spec/XMI/2.1";	//for uml file
	final String EMX_XMI_NS = "http://www.omg.org/XMI";	//for emx file
	final String DELIM = ", ";
	
	String ROOT_XPATH = "//packagedElement";
	String PROC_XPATH = "packagedElement[@xmi:type='uml:Class']";

	String IN_FILE_NAME = "";
	
	public static final String OUT_FILE = "RateChartModel.xls";
	FileOutputStream fstream = null;
    BufferedWriter out = null;
    HSSFWorkbook book = null;
	HSSFCellStyle LEFT_ALIGN_CELL_STYLE = null;
	String[] header = new String[] { "Arch Element Name", "Stereo Type", "Maturity", "Release", "Wave", "WIPT", "IST", "Est.Comp"};  
	String[] integrationHeader = new String[] { "Src Elem Type", "Src Elem Name", "Association Name", "Ref Elem Type", "Re Elem Name" };  
    int nCurrentRow = 0;
    
    HashMap<String, AbstractSOAData> objectsMap = new HashMap<String, AbstractSOAData>();
	HashMap<String, String> profileTypeList = new HashMap<String, String>();
    
	XPathFactory xpathFactory = XPathFactory.newInstance();
	XPathExpression stereoTypeExpr = null;
	XPathExpression soaObjAttribsExpr = null; //for attributes
	XPathExpression associationTypehrefExpr = null; //for UML Association ownedEnd Type id retrieval
	XPathExpression operExpr = null;	//for pulling operations..
	
	private NamespaceContext getNameSpaceCtx () {
		NamespaceContext ctx = new NamespaceContext() {
	        public String getNamespaceURI(String prefix) {
	        	//System.out.println("Name space requested : " + prefix);
	            String uri = null;
	            if (prefix.equals("xmi")) {
	                uri = getNameSpaceURL();
	            } else if(prefix.equals("XSDProfile")) {
	            	uri = "http:///schemas/XSDProfile/100";
	            }
	            return uri;
	        }
	       
	        // Dummy implementation - not used!
	        public Iterator getPrefixes(String val) { return null; }
	       
	        // Dummy implemenation - not used!
	        public String getPrefix(String uri) { return null; }
	    };
	    return ctx;
	}
	
	private XPathExpression getXPathExpression(String xpathStr) throws Exception {
		XPath xpath = xpathFactory.newXPath();
		xpath.setNamespaceContext(getNameSpaceCtx());
		// XPath Query for showing all nodes value
		XPathExpression expr = xpath.compile(xpathStr);
		return expr;
	}
	
	public String getNameSpaceURL() {
		if(this.IN_FILE_NAME.endsWith("emx"))
			return EMX_XMI_NS;
		return UML_XMI_NS;
	}
	private NodeList evaluate(Object evalOn, XPathExpression expr) throws Exception {
		Object result = expr.evaluate(evalOn, XPathConstants.NODESET);
		NodeList nodes = (NodeList) result;
		return nodes;
	}

	private void printReferenceEntityDetails(HSSFRow row, String srcStereoType, String srcEName, 
			String assocName, String destStereoType, String destEName) {
		int i = 0;
		HSSFCell cell = row.createCell(i++);
		cell.setCellValue(srcStereoType);
		cell = row.createCell(i++);
		cell.setCellValue(srcEName);
		cell = row.createCell(i++);
		cell.setCellValue(assocName);
		cell = row.createCell(i++);
		cell.setCellValue(destStereoType);
		cell = row.createCell(i++);
		cell.setCellValue(destEName);
		cell = row.createCell(i++);
	}

	private void printInterfaceDetails(HSSFRow row, Interface soaObj, SOAData soaData) {
		int i = 0;
		HSSFCell cell = row.createCell(i++);
		cell.setCellValue(soaObj.name);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.stereotype);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.maturity);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.release);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.relWave);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.wipt);
		cell = row.createCell(i++);
		cell.setCellValue(soaObj.IST);
		cell = row.createCell(i++);
		// for estimated component ID
		String compID = "";
		List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.INTR);
		for (EntitiesReferences entRef : entList) {
			if (EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
				if (compID.length() > 0)
					compID += ", ";
				compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
			}
		}
		cell.setCellValue(compID);
		cell = row.createCell(i++);
	}
	
	private void printAllInterfaces(SOAData soaData, HSSFWorkbook book) {
		ArrayList<Interface> soaObjList = (ArrayList<Interface>) soaData.intList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("System Interfaces");
	    printHeader(sheet, header);
		for(Interface soaObj : soaObjList) {
			if(soaObj.stereotype.indexOf("System Interface") <= 0)
				continue;
			HSSFRow row = sheet.createRow(nCurrentRow++);
			printInterfaceDetails(row, soaObj, soaData);
		}
		nCurrentRow = 0;
	    sheet = book.createSheet("Internal Interfaces");
	    printHeader(sheet, header);
		for(Interface soaObj : soaObjList) {
			if(soaObj.stereotype.indexOf("Internal Interface") <= 0)
				continue;
			HSSFRow row = sheet.createRow(nCurrentRow++);
			printInterfaceDetails(row, soaObj, soaData);
		}
		nCurrentRow = 0;
	    sheet = book.createSheet("User Interfaces");
	    printHeader(sheet, header);
		for(Interface soaObj : soaObjList) {
			if(soaObj.stereotype.indexOf("Portal") <= 0)
				continue;
			HSSFRow row = sheet.createRow(nCurrentRow++);
			printInterfaceDetails(row, soaObj, soaData);
		}

		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("Intrface to Proc Int");
	    printHeader(sheet, integrationHeader);
	    Processes procObj = null;
		for(Interface soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForSourceTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.INTR);
			for (EntitiesReferences entRef : entList) {
				if (EntityType.PROC.toString().equalsIgnoreCase(entRef.reftype)) {
					procObj = (Processes) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							procObj.stereotype, procObj.name);
				}
			}
		}
		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("Intrface to Serv Int");
	    printHeader(sheet, integrationHeader);
	    Service servObj = null;
		for(Interface soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForSourceTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.INTR);
			for (EntitiesReferences entRef : entList) {
				if (EntityType.SERV.toString().equalsIgnoreCase(entRef.reftype)) {
					servObj = (Service) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							servObj.stereotype, servObj.name);
				}
			}
		}
	}
	private void printAllProcesses(SOAData soaData, HSSFWorkbook book) {
		ArrayList<Processes> soaObjList = (ArrayList<Processes>) soaData.procList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Processes");
	    printHeader(sheet, header);
		for(Processes soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereotype);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);
			//for estimated component ID
			String compID = "";
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.PROC);
			for(EntitiesReferences entRef : entList) {
				if(EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
					if(compID.length() > 0)
						compID += ", ";
					compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
				}
			}
			cell.setCellValue(compID);
			cell = row.createCell(i++);
		}
		
		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("Proc to Serv Int");
	    printHeader(sheet, integrationHeader);
	    Service servObj = null;
		for(Processes soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForSourceTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.PROC);
			for (EntitiesReferences entRef : entList) {
				if (EntityType.SERV.toString().equalsIgnoreCase(entRef.reftype)) {
					servObj = (Service) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							servObj.stereotype, servObj.name);
				}
			}
		}
	}
	private void printAllServices(SOAData soaData, HSSFWorkbook book) {
		ArrayList<Service> soaObjList = (ArrayList<Service>) soaData.servList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Services");
	    printHeader(sheet, header);
		for(Service soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereotype);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);			
			//for estimated component ID
			String compID = "";
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.SERV);
			for(EntitiesReferences entRef : entList) {
				if(EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
					if(compID.length() > 0)
						compID += ", ";
					compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
				}
			}
			cell.setCellValue(compID);
			cell = row.createCell(i++);
		}
		
		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("Serv to Serv Int");
	    printHeader(sheet, integrationHeader);
	    Service servObj = null;
		for(Service soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForSourceTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.SERV);
			for (EntitiesReferences entRef : entList) {
				if (EntityType.SERV.toString().equalsIgnoreCase(entRef.reftype)) {
					servObj = (Service) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							servObj.stereotype, servObj.name);
				}
			}
		}
		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("Serv to Intrface Int");
	    printHeader(sheet, integrationHeader);
	    Interface intObj = null;
	    ComponentModel cmpModel = null;
		for(Service soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForSourceTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.SERV);
			for (EntitiesReferences entRef : entList) {
				if (EntityType.INTR.toString().equalsIgnoreCase(entRef.reftype)) {
					intObj = (Interface) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							intObj.stereotype, intObj.name);
				} else if (EntityType.COMP.toString().equalsIgnoreCase(entRef.reftype)) {
					cmpModel = (ComponentModel) this.objectsMap.get(entRef.refEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.name, entRef.refQualifier,
							cmpModel.stereotype, cmpModel.name);
				}
			}
		}
	}
	private void printAllApplications(SOAData soaData, HSSFWorkbook book) {
		ArrayList<Application> soaObjList = (ArrayList<Application>) soaData.appList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Applications");
	    printHeader(sheet, header);
		for(Application soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereoType);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);			
			//for estimated component ID
			String compID = "";
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.APPL);
			for(EntitiesReferences entRef : entList) {
				if(EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
					if(compID.length() > 0)
						compID += ", ";
					compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
				}
			}
			cell.setCellValue(compID);
			cell = row.createCell(i++);
		}
	}
	private void printAllIntegrationComponents(SOAData soaData, HSSFWorkbook book) {
		ArrayList<IntegrationComp> soaObjList = (ArrayList<IntegrationComp>) soaData.intCompList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Configurations");
	    printHeader(sheet, header);
		for(IntegrationComp soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereoType);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);			
			//for estimated component ID
			String compID = "";
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.INTUC);
			for(EntitiesReferences entRef : entList) {
				if(EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
					if(compID.length() > 0)
						compID += ", ";
					compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
				}
			}
			cell.setCellValue(compID);
			cell = row.createCell(i++);
		}
	}
	private void printAllRuleSets(SOAData soaData, HSSFWorkbook book) {
		ArrayList<RuleSet> soaObjList = (ArrayList<RuleSet>) soaData.rSetsList;
		
		if(soaObjList == null)
			return;
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("RuleSets");
	    printHeader(sheet, header);
		for(RuleSet soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereoType);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.domain);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);
			if(soaObj.rulesList == null)
				continue;
			for(Rule rl : soaObj.rulesList) {
				row = sheet.createRow(nCurrentRow++);
				i = 0;
				cell = row.createCell(i++);
				cell.setCellValue(rl.name);
				cell.setCellStyle(LEFT_ALIGN_CELL_STYLE);
				cell = row.createCell(i++);
				cell.setCellValue(Rule.STEREO_TYPE);
				cell = row.createCell(i++);
				cell.setCellValue(rl.maturity);
				cell = row.createCell(i++);
				cell.setCellValue(soaObj.release);
				cell = row.createCell(i++);			
				cell.setCellValue(soaObj.relWave);
				cell = row.createCell(i++);
				cell.setCellValue(soaObj.domain);
				cell = row.createCell(i++);			
				cell.setCellValue(soaObj.IST);
				cell = row.createCell(i++);
			}
		}
	}

	private void printAllComponentModels(SOAData soaData, HSSFWorkbook book) {
		ArrayList<ComponentModel> soaObjList = (ArrayList<ComponentModel>) soaData.compModelList;
		
		if(soaObjList == null)
			return;
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Component Models");
	    printHeader(sheet, header);
		for(ComponentModel soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.name);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereotype);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.maturity);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.release);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.IST);
			cell = row.createCell(i++);			
			//for estimated component ID
			String compID = "";
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.INTUC);
			for(EntitiesReferences entRef : entList) {
				if(EntityType.PROP.toString().equalsIgnoreCase(entRef.entitytype)) {
					if(compID.length() > 0)
						compID += ", ";
					compID += (((RelatedProperties) this.objectsMap.get(entRef.srcEntityHashableId)).propValue);
				}
			}
			cell.setCellValue(compID);
			cell = row.createCell(i++);
		}
	}

	private void printAllMessageClasses(SOAData soaData, HSSFWorkbook book) {
		ArrayList<DataClass> soaObjList = (ArrayList<DataClass>) soaData.dataList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Message Classes");
	    printHeader(sheet, header);
		for(DataClass soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.ename);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereoType);
			cell = row.createCell(i++);
			cell.setCellValue("-1");	//maturity
			cell = row.createCell(i++);
			cell.setCellValue("A");		//release
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.application);	//IST
			cell = row.createCell(i++);			
			cell.setCellValue("");		//est comp ids
			cell = row.createCell(i++);
		}
	}

	private void printAllRequirements(SOAData soaData, HSSFWorkbook book) {
		ArrayList<UseCase> soaObjList = (ArrayList<UseCase>) soaData.useCaseList;
		
		nCurrentRow = 0;
	    HSSFSheet sheet = book.createSheet("Requirements");
	    printHeader(sheet, header);
		for(UseCase soaObj : soaObjList) {
			HSSFRow row = sheet.createRow(nCurrentRow++);
			int i = 0;
			HSSFCell cell = row.createCell(i++);
			cell.setCellValue(soaObj.uname);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.stereotype);
			cell = row.createCell(i++);
			cell.setCellValue("");	//maturity
			cell = row.createCell(i++);
			cell.setCellValue("A");		//release
			cell = row.createCell(i++);			
			cell.setCellValue(soaObj.relWave);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.wipt);
			cell = row.createCell(i++);
			cell.setCellValue(soaObj.IST);	//IST
			cell = row.createCell(i++);			
			cell.setCellValue("");		//est comp ids
			cell = row.createCell(i++);
		}
		//now print all the integrations..
		nCurrentRow = 0;
	    sheet = book.createSheet("UC to ArchComp");
	    printHeader(sheet, integrationHeader);
	    Service servObj = null;
	    Processes procObj = null;
		for(UseCase soaObj : soaObjList) {
			List<EntitiesReferences> entList = Utils.findEntitiesReferencesForRefTypeHashID(soaData.entityRef, soaObj.xmiID, EntityType.USEC);
			if(entList == null || entList.size() == 0) {
				HSSFRow row = sheet.createRow(nCurrentRow++);
				printReferenceEntityDetails(row, soaObj.stereotype, soaObj.uname, "None", "None", "None");
				continue;
			}
			for (EntitiesReferences entRef : entList) {
				if (EntityType.SERV.toString().equalsIgnoreCase(entRef.entitytype)) {
					servObj = (Service) this.objectsMap.get(entRef.srcEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.uname, entRef.refQualifier,
							servObj.stereotype, servObj.name);
				} else if (EntityType.PROC.toString().equalsIgnoreCase(entRef.entitytype)) {
					procObj = (Processes) this.objectsMap.get(entRef.srcEntityHashableId);
					HSSFRow row = sheet.createRow(nCurrentRow++);
					printReferenceEntityDetails(row, soaObj.stereotype, soaObj.uname, entRef.refQualifier,
							procObj.stereotype, procObj.name);
				}
			}
		}
	}

	public void transform(String inXML) throws Exception {
		long startTime = System.currentTimeMillis();
		IN_FILE_NAME = inXML;
		
		Document doc = getXMLDocument(inXML);
		//prep req values
		stereoTypeExpr = getXPathExpression("eAnnotations/details/@key");
		soaObjAttribsExpr = getXPathExpression("ownedAttribute/@name"); //for attributes
		associationTypehrefExpr = getXPathExpression("type/@href");
		operExpr = getXPathExpression("ownedOperation");
		
		fstream = new FileOutputStream(OUT_FILE);

	    book = new HSSFWorkbook();
	    //create final params used in the rest of the code, never changed.
		LEFT_ALIGN_CELL_STYLE = book.createCellStyle();
		LEFT_ALIGN_CELL_STYLE.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		LEFT_ALIGN_CELL_STYLE.setIndention((short)4);
		
		SOAData soaData = null;
		extractProfileTypes(doc);
		System.out.println("Extracted Profiles..");
		soaData = extractComponents(doc);
		associateMainClasses(doc);
		extractDependencies(soaData, doc);
		
		printAllInterfaces(soaData, book);
		printAllProcesses(soaData, book);
		printAllServices(soaData, book);
		printAllApplications(soaData, book);
		printAllIntegrationComponents(soaData, book);
		printAllRuleSets(soaData, book);
		printAllComponentModels(soaData, book);
		printAllMessageClasses(soaData, book);
		printAllRequirements(soaData, book);
		
		if(out != null) {
			out.close();
		}
		if(book != null) {
//			CellRangeAddress range = new CellRangeAddress(0, this.nCurrentRow-1, 0, header.length-1);
//			sheet.setAutoFilter(range);
			book.write(fstream);
			fstream.close();
		}

		System.out.println("Time took : " + (System.currentTimeMillis() - startTime)/1000 + " sec");
	}
	
	private SOAData extractInterfaces(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<Interface> soaObjList = (ArrayList<Interface>) soaData.intList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<Interface>();
			soaData.intList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			Interface soaObj = new Interface();
			objNode = nodes.item(j);
			soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.stereotype = getStereoType(objNode);
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			soaObj.maturity = getAttributeValue(objNode, "Maturity");
			soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}

	private SOAData extractProcesses(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<Processes> soaObjList = new ArrayList<Processes>();
		soaData.procList = soaObjList;
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			Processes soaObj = new Processes();
			objNode = nodes.item(j);
			soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.stereotype = getStereoType(objNode);
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			soaObj.maturity = getAttributeValue(objNode, "Maturity");
			soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}

	private SOAData extractServices(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<Service> soaObjList = new ArrayList<Service>();
		soaData.servList = soaObjList;
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			Service soaObj = new Service();
			objNode = nodes.item(j);
			soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.stereotype = getStereoType(objNode);
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			soaObj.maturity = getAttributeValue(objNode, "Maturity");
			soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}

	private SOAData extractApplications(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<Application> soaObjList = new ArrayList<Application>();
		soaData.appList = soaObjList;
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			objNode = nodes.item(j);
			String stereoType = getStereoType(objNode);
			if("IOE Application".equalsIgnoreCase(stereoType)) {
				Application soaObj = new Application();
				soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
				soaObj.stereoType = stereoType;
				soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
				soaObj.maturity = getAttributeValue(objNode, "Maturity");
				soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
				objectsMap.put(soaObj.xmiID, soaObj);
				soaObjList.add(soaObj);
			}
		}
		return soaData;
	}

	private SOAData extractIntegrationComponents(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<IntegrationComp> soaObjList = (ArrayList<IntegrationComp>) soaData.intCompList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<IntegrationComp>();
			soaData.intCompList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
		
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			IntegrationComp soaObj = new IntegrationComp();
			objNode = nodes.item(j);
			soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.stereoType = getStereoType(objNode);
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			soaObj.maturity = getAttributeValue(objNode, "Maturity");
			soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}

	private SOAData extractRuleSets(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<RuleSet> soaObjList = (ArrayList<RuleSet>) soaData.rSetsList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<RuleSet>();
			soaData.rSetsList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null, attribNode = null;
		String pkgType = "";
		for (int j = 0; j < nodes.getLength(); j++) {
			objNode = nodes.item(j);
			pkgType = getNamedAttributeValueNS(objNode, "type");
			if("uml:Package".equalsIgnoreCase(pkgType)) {
				extractRuleSets(soaData, objNode.getChildNodes());
				continue;
			} else if("uml:Class".equalsIgnoreCase(pkgType)) {
				RuleSet soaObj = new RuleSet();
				soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
				soaObj.stereoType = getStereoType(objNode);
				soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
				soaObj.maturity = getAttributeValue(objNode, "Maturity");
				soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
				soaObj.domain = getNamedAttributeValue(objNode.getParentNode(), "name");
				//now pull all the opeartions..
				NodeList operNodes = evaluate(objNode, operExpr);
				for(int k = 0; k < operNodes.getLength(); k++) {
					attribNode = operNodes.item(k);
					String opName = getNamedAttributeValue(attribNode, "name");
					Rule tRule = new Rule();
					tRule.name = opName;
					tRule.maturity = getAttributeValue(objNode, "Maturity");
					tRule.relWave = getAttributeValue(objNode, WAVE_STR);
					soaObj.add(tRule);
				}
				
				objectsMap.put(soaObj.xmiID, soaObj);
				soaObjList.add(soaObj);
			}
		}
		return soaData;
	}

	private SOAData extractEstimatingComponents(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<RelatedProperties> soaObjList = new ArrayList<RelatedProperties>();
		soaData.propsList = soaObjList;
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			RelatedProperties soaObj = new RelatedProperties();
			objNode = nodes.item(j);
			soaObj.propName = "COMP_ID";
			soaObj.propValue = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}
	
	private SOAData extractComponentModels(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<ComponentModel> soaObjList = (ArrayList<ComponentModel>) soaData.compModelList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<ComponentModel>();
			soaData.compModelList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			ComponentModel soaObj = new ComponentModel();
			objNode = nodes.item(j);
			soaObj.name = objNode.getAttributes().getNamedItem("name").getNodeValue();
			soaObj.stereotype = getStereoType(objNode);
			soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
			soaObj.maturity = getAttributeValue(objNode, "Maturity");
			soaObj.relWave = getAttributeValue(objNode, WAVE_STR);
			soaObj.IST = getNamedAttributeValue(objNode.getParentNode(), "name");
			
			objectsMap.put(soaObj.xmiID, soaObj);
			soaObjList.add(soaObj);
		}
		return soaData;
	}

	private SOAData extractMessageClasses(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<DataClass> soaObjList = (ArrayList<DataClass>) soaData.dataList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<DataClass>();
			soaData.dataList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		Node parentNode = null, oldParentNode = null;
		String parentName = "";
		String pkgType = "";
		
		for (int j = 0; j < nodes.getLength(); j++) {
			objNode = nodes.item(j);
			pkgType = getNamedAttributeValueNS(objNode, "type");
			if("uml:Package".equalsIgnoreCase(pkgType)) {
				extractMessageClasses(soaData, objNode.getChildNodes());
				continue;
			} else if("uml:Class".equalsIgnoreCase(pkgType)) {
				DataClass soaObj = new DataClass();
				soaObj.ename = objNode.getAttributes().getNamedItem("name").getNodeValue();
				soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
				soaObj.stereoType = (String) profileTypeList.get(soaObj.xmiID);
				
				parentNode = objNode;
				oldParentNode = parentNode; 
				while(parentNode != null) {
					parentName = getNamedAttributeValue(parentNode, "name");
					if("019_Message Classes".equalsIgnoreCase(parentName) == true) { 
						parentNode = oldParentNode;
						break;
					}
					oldParentNode = parentNode; 
					parentNode = parentNode.getParentNode();
				}
				soaObj.application = getNamedAttributeValue(parentNode, "name");
				//no mapping necessary at this time - RSingh 03/01/2011.
				//objectsMap.put(soaObj.xmiID, soaObj);
				soaObjList.add(soaObj);
			}
		}
		return soaData;
	}
	
	private SOAData extractRequirements(SOAData soaData, NodeList nodes) throws Exception {
		ArrayList<UseCase> soaObjList = (ArrayList<UseCase>) soaData.useCaseList;
		
		if(soaObjList == null) {
			soaObjList = new ArrayList<UseCase>();
			soaData.useCaseList = soaObjList;
		}
		
		if (nodes == null || nodes.getLength() == 0)
			return soaData;
						
		Node objNode = null;
		String pkgType = "", pkgName = "";
		for (int j = 0; j < nodes.getLength(); j++) {
			objNode = nodes.item(j);
			pkgType = getNamedAttributeValueNS(objNode, "type");
			if("uml:Package".equalsIgnoreCase(pkgType)) {
				pkgName = objNode.getAttributes().getNamedItem("name").getNodeValue();
				if(!"Removed".equalsIgnoreCase(pkgName))
					extractRequirements(soaData, objNode.getChildNodes());
				continue;
			} else if("uml:Class".equalsIgnoreCase(pkgType) || "uml:UseCase".equalsIgnoreCase(pkgType)) {
				UseCase soaObj = new UseCase();
				soaObj.uname = objNode.getAttributes().getNamedItem("name").getNodeValue();
				soaObj.stereotype = getStereoType(objNode);
				soaObj.xmiID = objNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
				soaObj.relWave = "A.1";
				
				objectsMap.put(soaObj.xmiID, soaObj);
				soaObjList.add(soaObj);
			}
		}
		return soaData;
	}

	private SOAData extractComponents(Document doc) throws Exception {
		String[] pkgNames = { "005_System Interfaces", "006_Internal Interfaces", "007_Processes",
				"008_Services", "010_Applications", "012_Hosting Config", "013_Security Config", 
				"014_Integration Config", "021_Rule Sets", "022_Rule Tasks",
				"003_User Interfaces", "020_Estimating Components", "023_Component Model",
				"019_Message Classes", "017_Requirements"
				};
		XPathExpression subPkgXPathExpr = getXPathExpression("packagedElement[@xmi:type='uml:Class']");
		XPathExpression sub_subPkgXPathExpr = getXPathExpression("packagedElement/packagedElement[@xmi:type='uml:Class']");
		
		SOAData soaData = new SOAData();
		int pkgNumber = -1;
		for(int i = 0; i < pkgNames.length; i++) {
			pkgNumber = Integer.parseInt(pkgNames[i].substring(0, 3));
			NodeList nodes = evaluate(doc, getXPathExpression("//packagedElement[@name='" + pkgNames[i] + "']"));
			Node procRootFolderNode = nodes.item(0);
			//MessageClasses, RuleSets and RuleTaks, and Requirements
			if(pkgNumber != 19 && pkgNumber != 21 && pkgNumber != 22 && pkgNumber != 17) {	
				nodes = evaluate(procRootFolderNode, subPkgXPathExpr);
				if(nodes.getLength() == 0)
					nodes = evaluate(procRootFolderNode, sub_subPkgXPathExpr);
			}
			long startTime = System.currentTimeMillis();
			System.out.println("Started " + pkgNames[i]);
			if(pkgNumber == 5 || pkgNumber == 6 || pkgNumber == 3) {
				soaData = extractInterfaces(soaData, nodes);
			} else if(pkgNumber == 7) {
				soaData = extractProcesses(soaData, nodes);
			} else if(pkgNumber == 8) {
				soaData = extractServices(soaData, nodes);
			} else if(pkgNumber == 10) {
				soaData = extractApplications(soaData, nodes);
			} else if(pkgNumber == 12 || pkgNumber == 13 || pkgNumber == 14) {
				soaData = extractIntegrationComponents(soaData, nodes);
			} else if(pkgNumber == 21 || pkgNumber == 22) {
				if(isRateChartReport)
					soaData = extractRuleSets(soaData, nodes);
			} else if(pkgNumber == 20) {	//estimation components
				soaData = extractEstimatingComponents(soaData, nodes);
			} else if(pkgNumber == 23) {	//component models
				if(isRateChartReport)
					soaData = extractComponentModels(soaData, nodes);
			} else if(pkgNumber == 19 ) {	//messge classes
				soaData = extractMessageClasses(soaData, nodes);
			} else if(pkgNumber == 17 ) {	//Requirements
				soaData = extractRequirements(soaData, nodes);
			}
			System.out.println("Time took : " + (System.currentTimeMillis() - startTime)/1000 + " sec. Extracted " + pkgNames[i] );
			//System.out.println("Extracted " + pkgNames[i]);
		}
		return soaData;
	}
	
	private void extractProfileTypes(Document doc) throws Exception {
		profileTypeList.clear();
		
		XPathExpression elemXPathExpr = getXPathExpression("//XSDProfile:element");
		XPathExpression compXPathExpr = getXPathExpression("//XSDProfile:complexType");
		XPathExpression simpeXPathExpr = getXPathExpression("//XSDProfile:simpleType");

		NodeList nodes = evaluate(doc, elemXPathExpr);
		Node mainObjNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			mainObjNode = nodes.item(j);
			String baseClsID = getNamedAttributeValue(mainObjNode, "base_Class");
			if(Utils.isEmpty(baseClsID))
				continue;
			profileTypeList.put(baseClsID, "element");
		}
		nodes = evaluate(doc, compXPathExpr);
		mainObjNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			mainObjNode = nodes.item(j);
			String baseClsID = getNamedAttributeValue(mainObjNode, "base_Class");
			if(Utils.isEmpty(baseClsID))
				continue;
			profileTypeList.put(baseClsID, "complexType");
		}
		nodes = evaluate(doc, simpeXPathExpr);
		mainObjNode = null;
		for (int j = 0; j < nodes.getLength(); j++) {
			mainObjNode = nodes.item(j);
			String baseClsID = getNamedAttributeValue(mainObjNode, "base_Class");
			if(Utils.isEmpty(baseClsID))
				continue;
			profileTypeList.put(baseClsID, "simpleType");
		}
	}
	private void associateMainClasses(Document doc) throws Exception {
		HashMap<String, String> classesList = new HashMap<String, String>();

		//String[] pkgNames = { "00_Releases", "002_IST", "004_Management Functions", "020_Estimating Components" };
		String[] pkgNames = { "00_Releases", "002_IST", "004_Management Functions" };
		XPathExpression compSubPkgXPathExpr = getXPathExpression("packagedElement[@xmi:type='uml:Component']");
		//XPathExpression classPkgXPathExpr = getXPathExpression("packagedElement[@xmi:type='uml:Class']");
		
		for(int i = 0; i < pkgNames.length; i++) {
			NodeList nodes = evaluate(doc, getXPathExpression("//packagedElement[@name='" + pkgNames[i] + "']"));
			Node procRootFolderNode = nodes.item(0);
			nodes = evaluate(procRootFolderNode, compSubPkgXPathExpr);
			
			Node mainObjNode = null;
			
			for (int j = 0; j < nodes.getLength(); j++) {
				mainObjNode = nodes.item(j);
				String name = mainObjNode.getAttributes().getNamedItem("name").getNodeValue();
				String sXMI_ID = mainObjNode.getAttributes().getNamedItemNS(getNameSpaceURL(), "id").getNodeValue();
				classesList.put(sXMI_ID, name);
			}
		}
		
		Set<String> keySet = classesList.keySet();
		for(String key : keySet) {
			String sXMI_ID = key;
			String name = classesList.get(key);
			
			String xp = "//packagedElement[@xmi:type='uml:Association']/ownedEnd[@type='" + sXMI_ID + "']";
			//String xp = "//ownedEnd[@type='" + sXMI_ID + "']";
			//System.out.println(xp);
			XPathExpression associationsExpr = getXPathExpression(xp);
			NodeList associationNodes = evaluate(doc, associationsExpr);
			Node attribNode;
			ArrayList<String> associtionsIDs = null;
			String sibType = null;
			for(int j = 0; j < associationNodes.getLength(); j++) {
				attribNode = associationNodes.item(j);
				associtionsIDs = extractAssociationObject(attribNode.getParentNode());
				if(associtionsIDs == null || associtionsIDs.size() != 2)
					continue;
				if(sXMI_ID.equalsIgnoreCase(associtionsIDs.get(0)))
					sibType = associtionsIDs.get(1);
				else
					sibType = associtionsIDs.get(0);
				AbstractSOAData absSOAData = this.objectsMap.get(sibType);
				if(absSOAData == null) {
					System.out.println("Unable to locate Object for <<" + sibType + ">> that belongs to " + name + " has ownedEnd <<" + sXMI_ID + ">> ");
					continue;
				}
				if(absSOAData.getUMLType() == EntityType.APPL) {
					Application tObj = (Application)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.wipt =  name;
					}
				} else if(absSOAData.getUMLType() == EntityType.INTUC) {
					IntegrationComp tObj = (IntegrationComp)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.wipt =  name;
					}
				} else if(absSOAData.getUMLType() == EntityType.INTR) {
					Interface tObj = (Interface)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.wipt =  name;
					}
				} else if(absSOAData.getUMLType() == EntityType.PROC) {
					Processes tObj = (Processes)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.wipt =  name;
					}
				} else if(absSOAData.getUMLType() == EntityType.RSET) {
					RuleSet tObj = (RuleSet)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.domain =  name;
					}
				} else if(absSOAData instanceof Service) {
					Service tObj = (Service)absSOAData;
					if(name.startsWith(RELEASE_STR)) {
						tObj.release = parseRelaseString(name);
					} else {
						if(name.length() > 4)
							tObj.IST = name;
						else
							tObj.wipt =  name;
					}
				}
			}
		}
		return;
	}
	
	private ArrayList<String> extractAssociationObject (Node associationNode) throws Exception {
		NodeList children = associationNode.getChildNodes();
		Node child = null;
		ArrayList<String> idList = new ArrayList<String>();
		for(int i = 0; i < children.getLength(); i++) {
			child = children.item(i);
			if("ownedEnd".equalsIgnoreCase(child.getNodeName())) {
				String sibType = null;
				if(child.getAttributes().getNamedItem("type") == null) {
					NodeList tmpNodes = evaluate(child, associationTypehrefExpr);
					if(tmpNodes != null && tmpNodes.getLength() > 0) {
						sibType = tmpNodes.item(0).getNodeValue();
						sibType = sibType.replaceAll("%20", " ");
					} else {
						//System.out.println("**** <<" + sXMI_ID + ">> " + name + " has no ownedEnd of type defined.");
						continue;
					}
				} else {
					sibType = child.getAttributes().getNamedItem("type").getNodeValue();
				}
				if(Utils.isEmpty(sibType))
					continue;
				idList.add(sibType);
			}
		}
		return idList;
	}
		
	private void extractDependencies(SOAData soaData, Document doc) throws Exception {
		Node attribNode;
		NodeList associationNodes;
		String[] possiblePaths = { "//packagedElement[(@xmi:type='uml:Dependency')]"}; //, "//packagedElement/packagedElement[(@xmi:type='uml:Dependency')]" };
		
		ArrayList<EntitiesReferences> soaObjList = new ArrayList<EntitiesReferences>();
		soaData.entityRef = soaObjList;
		
		for(String deprootxpath : possiblePaths) {
		XPathExpression associationsExpr = getXPathExpression(deprootxpath);
		associationNodes = evaluate(doc, associationsExpr);
		
		String supplierid = null;
		String depname = null;
		String client = null;
		
		for(int j = 0; j < associationNodes.getLength(); j++) {
			attribNode = associationNodes.item(j);
			depname = getNamedAttributeValue(attribNode, "name");
			client = getNamedAttributeValue(attribNode, "client");
			if(attribNode.getAttributes().getNamedItem("supplier") == null) {
				NodeList tmpNodes = evaluate(attribNode, getXPathExpression("supplier/@href"));
				if(tmpNodes != null && tmpNodes.getLength() > 0) {
					supplierid = tmpNodes.item(0).getNodeValue().replaceAll("%20", " ");
					supplierid = supplierid.substring(supplierid.lastIndexOf('/'));
				} else {
					//System.out.println("**** <<" + process.stereotype + ">> " + process.name + " has no Supplier of type : " + depname);
					continue;
				}
			} else {
				supplierid = attribNode.getAttributes().getNamedItem("supplier").getNodeValue();
			}
			AbstractSOAData clientSOAData = this.objectsMap.get(client);
			AbstractSOAData supSOAData = this.objectsMap.get(supplierid);
			if(clientSOAData == null || supSOAData == null)
				continue;
			EntitiesReferences soaObj = new EntitiesReferences();
			soaObj.srcEntityHashableId = clientSOAData.xmiID;
			soaObj.entitytype = clientSOAData.getUMLType().toString();
			soaObj.refQualifier = Utils.isEmpty(depname) ? null : depname.trim();
			soaObj.refEntityHashableId = supSOAData.xmiID;
			soaObj.reftype = supSOAData.getUMLType().toString();
			soaObjList.add(soaObj);
		}
		}
	}

	private String getStereoType(Node node) throws Exception {
		//XPathExpression stereoTypeExpr = getXPathExpression("eAnnotations/details/@key");
		NodeList attrbNodes = evaluate(node, stereoTypeExpr);
		if(attrbNodes == null || attrbNodes.getLength() == 0)
			return "NONE";
		String stereotype = attrbNodes.item(0).getNodeValue();
		return stereotype;
	}
	
	private String getAttributeValue(Node node, String attribName) throws Exception {
		String ret = "-1";
		
		NodeList procAttrbNodes = evaluate(node, soaObjAttribsExpr);
		Node attribNode = null;
		String name = null;
		String value = null;
		String toks[] = null;
		
		for(int j = 0; j < procAttrbNodes.getLength(); j++) {
			attribNode = procAttrbNodes.item(j);
			toks = attribNode.getNodeValue().split("=");
			if(toks.length != 2)
				continue;
			name = toks[0].trim();
			value = toks[1].trim();
			
			if(name.equalsIgnoreCase(attribName)) {
				ret = value.trim();
				break;
			}
			/*
			try {
				if(name.equalsIgnoreCase(attribName))
					ret = Integer.parseInt(value);
			} catch(NumberFormatException e) {
				ret = 9;	//needs this to be changed to A,B or C
			}
			*/
		}
		return ret;
	}
	
	private String getNamedAttributeValue(Node node, String attribName) throws Exception {
		String ret = "";
		
		NamedNodeMap attribMap = node.getAttributes();
		if(attribMap != null) {
			Node attribNode = attribMap.getNamedItem(attribName);
			if(attribNode != null)
				ret = attribNode.getNodeValue();
		}
		return ret;
	}

	private String getNamedAttributeValueNS(Node node, String attribName) throws Exception {
		String ret = "";

		NamedNodeMap attribMap = node.getAttributes();
		if(attribMap != null) {
			Node attribNode = attribMap.getNamedItemNS(getNameSpaceURL(), attribName);
			if(attribNode != null)
				ret = attribNode.getNodeValue();
		}
		return ret;
	}

	private String parseRelaseString(String release) {
		String ret = "-";
		int idx = release.indexOf(RELEASE_STR);
		if(idx >= 0) {
			ret = release.substring(RELEASE_STR.length());
			ret = ret.trim();
		}
		return ret;
	}
	private Document getXMLDocument(String inXML)
			throws ParserConfigurationException, SAXException, IOException {
		InputStream inXMLStream = this.getClass().getClassLoader().getResourceAsStream(inXML);

		DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
		domFactory.setNamespaceAware(true);
		DocumentBuilder builder = domFactory.newDocumentBuilder();
		Document doc = builder.parse(inXMLStream);
		return doc;
	}
	
	private void printHeader(HSSFSheet sheet, String[] headerList) {
		HSSFRow row = sheet.createRow(nCurrentRow++);
		String data = "";
		for(int i = 0; i < headerList.length; i++) {
			data = (String)headerList[i];
			HSSFCell cell = row.createCell(i);
			HSSFCellStyle style = book.createCellStyle();
			style.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
			style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
			style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
			cell.setCellStyle(style);
			cell.setCellValue(data);
		}
	}
}
